package com.demo.controller;

import com.alibaba.fastjson.JSON;
import com.demo.function.spring.feign.MiyaFeignClient;
import com.demo.function.spring.feign.MiyaFeignClientV2;
import com.demo.miya.controller.client.MiyaClient;
import com.demo.model.entity.User;
import com.demo.starter.dto.GeneralResult;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

/**
 * springcloud 基本入门控制层
 * 测试链接： <a href="http://localhost:8763/started/hi?name=forezp">http://localhost:8763/started/hi?name=forezp</a>
 * Spring Bean重新初始化并载入新的配置内容，修改配置文件后不用重启服务重新加载
 * 需要动态更新配置信息，只要在提供服务的类添加@RefreshScope
 * @author K
 *
 */
@Slf4j
@RestController
@RefreshScope
public class StartedController {

	@Value("${server.port}")
	String port;

	/**
	 *  读取配置中心属性
 	 */
	@Value("${foo:默认值}")
	String foo;

	@Resource
	private MiyaClient miyaClient;
	@Resource
	private MiyaFeignClient miyaFeignClient;
	@Resource
	private MiyaFeignClientV2 miyaFeignClientV2;

	/**
	 * 测试读取配置中心的配置
	 * 根据readme配置在nacos配置sentinel流控规则，该接口进行流控规则限制
 	 */
	@GetMapping("/started/hi")
	public String hi(@RequestParam String name) {
		String hi = "hi " + name + ",i am from port:" + port + ", config:" + foo;
		log.info("/hi服务：{}", hi);
		return hi;
	}

	/**
	 * 请求通过springcloud gateway转发到该接口
	 * @param user user对象
	 * @return user对象
	 */
	@PostMapping("/started/testGateway")
	public GeneralResult<User> testGateway(@RequestBody User user) {
		log.info("testGateWay 入参：{}", JSON.toJSONString(user));
		return GeneralResult.success(user);
	}

	/**
	 * 必须启动 miya 服务
	 * 开启wiremock 测试，不需要启动miya服务
	 * 引用miyaClient包，采用类似RPC方式调用
	 * @return String
	 */
	@GetMapping("/started/miyaHi")
	public String miyaHi() {
		log.info("调用miyaClient");
		return miyaClient.hi();
	}

	/**
	 * 必须启动 miya 服务
	 * 开启wiremock 测试，不需要启动miya服务
	 * 引用miyaClient包，采用类似RPC方式调用
	 * @return String
	 */
	@GetMapping("/started/miyaRequestMapping")
	public String miyaRequestMapping() {
		log.info("调用miyaClient接口miyaRequestMapping");
		return miyaClient.requestMapping("param18");
	}

	/**
	 * post表单请求参数转对象
	 * 测试请求参数拼接在url上，如：/started/request/param/to/object?userId=1&userName=2。
	 * 测试form表单请求
	 * SpringMVC将参数转换成对象
	 * 注意：不要使用@RequestParam注解，否则报错
	 * @param user 请求参数
	 * @return 返回字符串success
	 */
	@PostMapping("/started/request/param/to/object")
	public String paramToObject(User user) {
		log.info(JSON.toJSONString(user));
		return "success";
	}

	/**
	 * 必须启动 miya 服务
	 * 测试openfeign调用，服务提供方服务异常，openfeign fallback降级处理
	 * @param user 用户对象
	 * @return 用户结果
	 */
	@PostMapping("/modifyUserException")
	public User modifyUserException(@RequestBody User user) {
		User result = miyaFeignClient.modifyUserException(user);
		userLog(result);
		return result;
	}

	/**
	 * 必须启动 miya 服务
	 * 测试openfeign调用，服务提供方服务异常，openfeign fallbackFactorry降级处理
	 * @param user 用户对象
	 * @return 用户结果
	 */
	@PostMapping("/modifyUserException/v2")
	public User modifyUserExceptionV2(@RequestBody User user) {
		User result = miyaFeignClientV2.modifyUserException(user);
		userLog(result);
		return result;
	}

	/**
	 * 对使用openfeign调用耗时过长进行服务降级处理
	 * 根据readme配置在nacos配置sentinel熔断规则，该miya服务/processLongTime接口进行熔断降级
	 * @param timeout 超时时间
	 * @return 用户结果
	 */
	@GetMapping("/processLongTime")
	public User processLongTime(@RequestParam("timeout") long timeout) {
		User user = miyaFeignClientV2.processLongTime(timeout);
		userLog(user);
		return user;
	}

	@GetMapping("/currentThread")
	public String currentThread() {
		// 打印当前线程，是否使用虚拟线程
		log.info("currentThread:{}", Thread.currentThread());
		return Thread.currentThread().toString();
	}

	/**
	 * 必须启动 miya 服务
	 * 开启wiremock 测试，不需要启动miya服务
	 * @param user 用户对象
	 * @return 用户结果
	 */
	@PostMapping("/started/modifyUser")
	public User modifyUser(@RequestBody User user) {
		User result = miyaFeignClient.modifyUser(user);
		userLog(result);
		return result;
	}

	private void userLog(User result) {
		log.info("result:{}", JSON.toJSONString(result));
	}
}
